package com.ruoyi.approval.service.impl;

import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.ArrayList;
import java.util.List;
import java.util.Set;
import java.util.HashSet;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.lang.Snowflake;
import com.ruoyi.approval.domain.ASchedulingApplicationVehicle;
import com.ruoyi.approval.dto.ApprovalRequestsDto;
import com.ruoyi.approval.mapper.ASchedulingApplicationVehicleMapper;
import com.ruoyi.approval.param.AddApprovalRequestsParam;
import com.ruoyi.approval.param.UpdateApprovalRequestsParam;
import com.ruoyi.common.core.domain.R;
import com.ruoyi.common.core.web.domain.AjaxResult;
import com.ruoyi.system.api.RemoteProcessLogService;
import com.ruoyi.system.api.RemoteVehiclesService;
import com.ruoyi.system.api.domain.*;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import com.ruoyi.approval.mapper.AApprovalRequestsMapper;
import com.ruoyi.approval.domain.AApprovalRequests;
import com.ruoyi.approval.service.IAApprovalRequestsService;

/**
 * 审批请求Service业务层处理
 *
 * @author ruoyi
 * @date 2025-04-02
 */
@Service
public class AApprovalRequestsServiceImpl implements IAApprovalRequestsService {
    private static final Long VEHICLE_STATUS_LOCKED = 1L;
    private static final Long VEHICLE_STATUS_FREE = 0L;
    private static final Long VEHICLE_STATUS_APPROVED = 2L;
    private static final Long APPLICATION_TYPE = 1L;
    private static final int SUCCESS_CODE = 200;

    @Autowired
    private AApprovalRequestsMapper aApprovalRequestsMapper;

    @Autowired
    private RemoteVehiclesService remoteVehiclesService;

    @Autowired
    private ASchedulingApplicationVehicleMapper aSchedulingApplicationVehicleMapper;

    @Autowired
    private RemoteProcessLogService remoteProcessLogService;

    /**
     * 查询审批请求
     *
     * @param id 审批请求主键
     * @return 审批请求
     */
    @Override
    public ApprovalRequestsDto selectAApprovalRequestsById(Long id) {
        // 查询审批请求详情
        AApprovalRequests aApprovalRequests = aApprovalRequestsMapper.selectAApprovalRequestsId(String.valueOf(id));
        if (aApprovalRequests == null) {
            throw new RuntimeException("该申请不存在");
        }

        // 查询关联的车辆调度申请
        List<ASchedulingApplicationVehicle> aSchedulingApplicationVehicles = aSchedulingApplicationVehicleMapper.selectASchedulingApplicationVehicleBySchedulingApplicationId(aApprovalRequests.getApprovalRequestsId(), APPLICATION_TYPE);
        if (aSchedulingApplicationVehicles.isEmpty()) {
            throw new RuntimeException("该申请不存在");
        }

        // 获取车辆信息
        Set<SysVehicles> sysVehicles = getSysVehiclesFromApplicationVehicles(aSchedulingApplicationVehicles);

        // 调用远程服务获取车辆详细信息
        R<Set<SysVechicleDto>> setR = remoteVehiclesService.selectVehicles(sysVehicles);
        if (SUCCESS_CODE != setR.getCode()) {
            throw new RuntimeException("有车辆信息未找到");
        }

        SysProcessLogSelect sysProcessLogSelect = new SysProcessLogSelect();
        sysProcessLogSelect.setBusinessType("审批请求");
        sysProcessLogSelect.setBusinessId(aApprovalRequests.getApprovalRequestsId());
        R<List<SysProcessLogDto>> logs = remoteProcessLogService.selectVehicles(sysProcessLogSelect);
        if (SUCCESS_CODE != logs.getCode()) {
            throw new RuntimeException("日志记录失败");
        }

        // 构建返回的审批请求DTO
        ApprovalRequestsDto approvalRequestsDto = new ApprovalRequestsDto();
        BeanUtil.copyProperties(aApprovalRequests, approvalRequestsDto);
        approvalRequestsDto.setSysVechicleDto(setR.getData());
        approvalRequestsDto.setSysProcessLogDto(logs.getData());

        return approvalRequestsDto;
    }

    /**
     * 查询审批请求列表
     *
     * @param aApprovalRequests 审批请求
     * @return 审批请求列表
     */
    @Override
    public List<AApprovalRequests> selectAApprovalRequestsList(AApprovalRequests aApprovalRequests) {
        // 查询审批请求列表
        return aApprovalRequestsMapper.selectAApprovalRequestsList(aApprovalRequests);
    }

    /**
     * 新增审批请求
     *
     * @param param 审批请求参数
     * @param user  当前用户
     * @return 结果
     */
    @Override
    public int insertAApprovalRequests(AddApprovalRequestsParam param, SysUser user) {
        // 将参数转换为审批请求对象
        AApprovalRequests aApprovalRequests = BeanUtil.toBean(param, AApprovalRequests.class);

        // 生成唯一的审批请求ID
        String repairNum = new Snowflake(1, 1).nextIdStr();
        checkOrderExists(repairNum);

        // 获取车辆信息并设置状态为已锁定
        Set<SysVehicles> sysVehicles = param.getSysVehicles();
        List<ASchedulingApplicationVehicle> aSchedulingApplicationVehicles = createSchedulingApplicationVehicles(repairNum, sysVehicles, VEHICLE_STATUS_LOCKED);

        // 调用远程服务更新车辆状态
        AjaxResult ajaxResult = remoteVehiclesService.updateStatus(sysVehicles);
        if (SUCCESS_CODE != (int) ajaxResult.get("code")) {
            throw new RuntimeException("有车辆预约失败");
        }

        // 设置审批请求的申请人信息和状态
        aApprovalRequests.setRequesterId(user.getUserId());
        aApprovalRequests.setRequesterName(user.getUserName());
        aApprovalRequests.setApprovalRequestsId(repairNum);
        aApprovalRequests.setApprovalResult(0L);

        // 插入车辆调度申请
        int i = aSchedulingApplicationVehicleMapper.insertASchedulingApplicationVehicleId(aSchedulingApplicationVehicles);
        if (i != aSchedulingApplicationVehicles.size()) {
            throw new RuntimeException("有车辆预约失败");
        }

        // 记录日志
        logProcess(user, repairNum, "创建", "提交了用车申请");

        // 插入审批请求
        return aApprovalRequestsMapper.insertAApprovalRequests(aApprovalRequests);
    }

    /**
     * 拒绝审批请求
     *
     * @param param 审批请求参数
     * @param user  当前用户
     * @return 结果
     */
    @Override
    public int updateAApprovalRequests(UpdateApprovalRequestsParam param, SysUser user) {
        // 获取审批请求ID
        Long id = Long.valueOf(param.getApprovalRequestsId());
        checkApprovalRequestExists(id);
        checkApprovalRequestProcessed(id);

        // 获取当前时间并格式化
        LocalDateTime now = LocalDateTime.now();
        DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
        String formattedDateTime = now.format(formatter);

        // 查询关联的车辆调度申请
        List<ASchedulingApplicationVehicle> aSchedulingApplicationVehicles = aSchedulingApplicationVehicleMapper.selectASchedulingApplicationVehicleBySchedulingApplicationId(String.valueOf(id), APPLICATION_TYPE);
        if (aSchedulingApplicationVehicles.isEmpty()) {
            throw new RuntimeException("未找到该申请订单");
        }

        // 获取车辆信息并设置状态为空闲
        Set<SysVehicles> sysVehicles = getSysVehiclesFromApplicationVehicles(aSchedulingApplicationVehicles);
        updateVehicleStatus(sysVehicles, VEHICLE_STATUS_FREE);

        // 更新审批请求状态和拒绝信息
        AApprovalRequests aApprovalRequests = BeanUtil.toBean(param, AApprovalRequests.class);
        aApprovalRequests.setApprovalResult(2L);
        aApprovalRequests.setApproverId(user.getUserId());
        aApprovalRequests.setApproverName(user.getUserName());
        aApprovalRequests.setApprovalDate(formattedDateTime);

        int i = aApprovalRequestsMapper.updateAApprovalRequests(aApprovalRequests);
        if (i == 0) {
            throw new RuntimeException("审批失败");
        }

        // 记录日志
        logProcess(user, param.getApprovalRequestsId(), "审核", "拒绝了订单为" + param.getApprovalRequestsId() + "的用车申请");

        return i;
    }

    /**
     * 批量删除审批请求
     *
     * @param ids 需要删除的审批请求主键
     * @return 结果
     */
    @Override
    public int deleteAApprovalRequestsByIds(Long[] ids) {
        // 批量删除审批请求
        return aApprovalRequestsMapper.deleteAApprovalRequestsByIds(ids);
    }

    /**
     * 通过审批请求信息
     *
     * @param id 审批请求主键
     * @param user 当前用户
     * @return 结果
     */
    @Override
    public int deleteAApprovalRequestsById(Long id, SysUser user) {
        checkApprovalRequestExists(id);
        checkApprovalRequestProcessed(id);

        // 获取当前时间并格式化
        LocalDateTime now = LocalDateTime.now();
        DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
        String formattedDateTime = now.format(formatter);

        // 查询关联的车辆调度申请
        List<ASchedulingApplicationVehicle> aSchedulingApplicationVehicles = aSchedulingApplicationVehicleMapper.selectASchedulingApplicationVehicleBySchedulingApplicationId(String.valueOf(id), APPLICATION_TYPE);
        if (aSchedulingApplicationVehicles.isEmpty()) {
            throw new RuntimeException("未找到该申请订单");
        }

        // 获取车辆信息并设置状态为已批准
        Set<SysVehicles> sysVehicles = getSysVehiclesFromApplicationVehicles(aSchedulingApplicationVehicles);
        updateVehicleStatus(sysVehicles, VEHICLE_STATUS_APPROVED);

        // 更新审批请求状态和通过信息
        AApprovalRequests aApprovalRequests = aApprovalRequestsMapper.selectAApprovalRequestsId(String.valueOf(id));
        aApprovalRequests.setApprovalResult(1L);
        aApprovalRequests.setApproverId(user.getUserId());
        aApprovalRequests.setApproverName(user.getUserName());
        aApprovalRequests.setApprovalDate(formattedDateTime);

        int i = aApprovalRequestsMapper.updateAApprovalRequests(aApprovalRequests);
        if (i == 0) {
            throw new RuntimeException("审批失败");
        }

        // 记录日志
        logProcess(user, aApprovalRequests.getApprovalRequestsId(), "审核", "通过了订单为" + aApprovalRequests.getApprovalRequestsId() + "的用车申请");

        return i;
    }

    /**
     * 检查审批请求是否存在
     *
     * @param id 审批请求主键
     */
    private void checkApprovalRequestExists(Long id) {
        AApprovalRequests aApprovalRequests = aApprovalRequestsMapper.selectAApprovalRequestsId(String.valueOf(id));
        if (aApprovalRequests == null) {
            throw new RuntimeException("该申请不存在");
        }
    }

    /**
     * 检查审批请求是否已处理
     *
     * @param id 审批请求主键
     */
    private void checkApprovalRequestProcessed(Long id) {
        AApprovalRequests aApprovalRequests = aApprovalRequestsMapper.selectAApprovalRequestsId(String.valueOf(id));
        if (aApprovalRequests.getApprovalResult() != 0) {
            throw new RuntimeException("该申请已处理");
        }
    }

    /**
     * 检查订单是否存在
     *
     * @param repairNum 审批请求ID
     */
    private void checkOrderExists(String repairNum) {
        List<ASchedulingApplicationVehicle> aSchedulingApplicationVehicles = aSchedulingApplicationVehicleMapper.selectASchedulingApplicationVehicleBySchedulingApplicationId(repairNum, APPLICATION_TYPE);
        if (!aSchedulingApplicationVehicles.isEmpty()) {
            throw new RuntimeException("已存在该申请订单");
        }
    }

    /**
     * 更新车辆状态
     *
     * @param sysVehicles 车辆集合
     * @param status      车辆状态
     */
    private void updateVehicleStatus(Set<SysVehicles> sysVehicles, Long status) {
        for (SysVehicles sysVehicle : sysVehicles) {
            sysVehicle.setStatus(status);
        }

        AjaxResult ajaxResult = remoteVehiclesService.updateStatus(sysVehicles);
        if (SUCCESS_CODE != (int) ajaxResult.get("code")) {
            throw new RuntimeException("有车辆修改状态失败");
        }
    }

    /**
     * 创建调度申请车辆
     *
     * @param repairNum 审批请求ID
     * @param sysVehicles 车辆集合
     * @param status      车辆状态
     * @return 调度申请车辆列表
     */
    private List<ASchedulingApplicationVehicle> createSchedulingApplicationVehicles(String repairNum, Set<SysVehicles> sysVehicles, Long status) {
        List<ASchedulingApplicationVehicle> aSchedulingApplicationVehicles = new ArrayList<>();
        for (SysVehicles sysVehicle : sysVehicles) {
            ASchedulingApplicationVehicle aSchedulingApplicationVehicle = new ASchedulingApplicationVehicle();
            aSchedulingApplicationVehicle.setSchedulingApplicationId(repairNum);
            aSchedulingApplicationVehicle.setVehicleId(sysVehicle.getId());
            aSchedulingApplicationVehicle.setType(APPLICATION_TYPE);
            aSchedulingApplicationVehicles.add(aSchedulingApplicationVehicle);
            sysVehicle.setStatus(status);
        }
        return aSchedulingApplicationVehicles;
    }

    // 提取的从调度申请车辆获取SysVehicles的方法
    /**
     * 从调度申请车辆获取SysVehicles
     *
     * @param aSchedulingApplicationVehicles 调度申请车辆列表
     * @return 车辆集合
     */
    private Set<SysVehicles> getSysVehiclesFromApplicationVehicles(List<ASchedulingApplicationVehicle> aSchedulingApplicationVehicles) {
        Set<SysVehicles> sysVehicles = new HashSet<>();
        for (ASchedulingApplicationVehicle aSchedulingApplicationVehicle : aSchedulingApplicationVehicles) {
            SysVehicles sysVehicle = new SysVehicles();
            sysVehicle.setId(aSchedulingApplicationVehicle.getVehicleId());
            sysVehicles.add(sysVehicle);
        }
        return sysVehicles;
    }

    /**
     * 记录操作日志
     *
     * @param user 用户信息
     * @param businessId 业务ID
     * @param operationType 操作类型
     * @param operationDetails 操作详情
     */
    private void logProcess(SysUser user, String businessId, String operationType, String operationDetails) {
        SysProcessLog sysProcessLog = new SysProcessLog();
        sysProcessLog.setBusinessType("审批请求");
        sysProcessLog.setBusinessId(businessId);
        sysProcessLog.setOperationType(operationType);
        sysProcessLog.setOperationTime(LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")));
        sysProcessLog.setOperatorId(user.getUserId());
        sysProcessLog.setOperationDetails(user.getNickName() + operationDetails);
        AjaxResult add = remoteProcessLogService.add(sysProcessLog);
        if (SUCCESS_CODE != (int) add.get("code")) {
            throw new RuntimeException("日志记录失败");
        }
    }
}
